package com.eas.biz.service.examResult.impl;

import java.util.LinkedList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.eas.biz.constants.BizConstants;
import com.eas.biz.dao.examResult.dataobject.ExamResultDO;
import com.eas.biz.dao.examResult.dataobject.ExamResultQuery;
import com.eas.biz.dao.examResult.interfaces.ExamResultDao;
import com.eas.biz.dao.examResultDetail.dataobject.ExamResultDetailDO;
import com.eas.biz.dao.examResultDetail.dataobject.ExamResultDetailQuery;
import com.eas.biz.dao.examResultDetail.interfaces.ExamResultDetailDao;
import com.eas.biz.service.exam.interfaces.ExamService;
import com.eas.biz.service.examResult.domain.ExamQuestionResult;
import com.eas.biz.service.examResult.domain.ExamResult;
import com.eas.biz.service.examResult.domain.ExamSubjectResult;
import com.eas.biz.service.examResult.interfaces.ExamResultService;

@Service("examResultService")
public class ExamResultServiceImpl implements ExamResultService {

    @Resource(name = "examCacheService")
    private ExamService examService;

    @Autowired
    private ExamResultDao examResultDao;

    @Autowired
    private ExamResultDetailDao examResultDetailDao;

    public int getExamStudentCountBySchool(long examId, long schoolId) {
        ExamResultQuery query = new ExamResultQuery();
        query.setExamId(examId);
        query.setSchoolId(schoolId);
        query.setSubject(BizConstants.TOTAL_SCORE_SUBJECT);
        return examResultDao.countByQuery(query);
    }

    public int getExamStudentCountByClass(long examId, long classId) {
        ExamResultQuery query = new ExamResultQuery();
        query.setExamId(examId);
        query.setClassId(classId);
        query.setSubject(BizConstants.TOTAL_SCORE_SUBJECT);
        return examResultDao.countByQuery(query);
    }

    public List<ExamResult> getExamResultList(long studentId, boolean withSubjectResult) {
        List<ExamResult> resultList = new LinkedList<ExamResult>();
        ExamResultQuery query = new ExamResultQuery();
        query.setStudentId(studentId);
        query.setSubject(BizConstants.TOTAL_SCORE_SUBJECT);
        List<ExamResultDO> list = examResultDao.selectByQuery(query);
        if (list != null) {
            for (ExamResultDO resultDO : list) {
                ExamResult result = null;
                if (withSubjectResult) {
                    result = getExamResult(resultDO.getExamId(), resultDO.getStudentId(), true);
                } else {
                    result = buildResult(resultDO);
                }
                resultList.add(result);
            }
        }
        return resultList;
    }

    public List<ExamResult> getExamResultList(long examId, long classId, boolean withSubjectResult,
            int pageNumber, int pageSize) {
        List<ExamResult> resultList = new LinkedList<ExamResult>();
        ExamResultQuery query = new ExamResultQuery();
        query.setExamId(examId);
        query.setClassId(classId);
        query.setSubject(BizConstants.TOTAL_SCORE_SUBJECT);
        query.setScoreOrder(true);
        if (pageNumber > 0 && pageSize > 0) {
            query.setPageNumber(pageNumber);
            query.setPageSize(pageSize);
        }
        List<ExamResultDO> list = examResultDao.selectByQuery(query);
        if (list != null) {
            for (ExamResultDO resultDO : list) {
                ExamResult result = null;
                if (withSubjectResult) {
                    result = getExamResult(examId, resultDO.getStudentId(), true);
                } else {
                    result = buildResult(resultDO);
                }
                resultList.add(result);
            }
        }
        return resultList;
    }

    public List<ExamResult> getExamResultList(long examId, long classId, boolean withSubjectResult) {
        return getExamResultList(examId, classId, withSubjectResult, 0, 0);
    }

    public List<ExamSubjectResult> getSubjectResultList(long studentId, String subject) {
        List<ExamSubjectResult> resultList = new LinkedList<ExamSubjectResult>();
        ExamResultQuery query = new ExamResultQuery();
        query.setStudentId(studentId);
        query.setSubject(subject);
        List<ExamResultDO> results = examResultDao.selectByQuery(query);

        if (results.size() > 0) {
            for (ExamResultDO resultDO : results) {
                resultList.add(buildSubjectResult(resultDO));
            }
        }
        return resultList;
    }

    public List<ExamSubjectResult> getSubjectResultList(long examId, long classId, String subject,
            int pageNumber, int pageSize) {
        List<ExamSubjectResult> resultList = new LinkedList<ExamSubjectResult>();
        ExamResultQuery query = new ExamResultQuery();
        query.setExamId(examId);
        query.setClassId(classId);
        query.setSubject(subject);
        query.setScoreOrder(true);
        if (pageNumber > 0 && pageSize > 0) {
            query.setPageNumber(pageNumber);
            query.setPageSize(pageSize);
        }
        List<ExamResultDO> results = examResultDao.selectByQuery(query);

        if (results.size() > 0) {
            for (ExamResultDO resultDO : results) {
                resultList.add(buildSubjectResult(resultDO));
            }
        }
        return resultList;
    }

    public List<ExamSubjectResult> getSubjectResultList(long examId, long classId, String subject) {
        return getSubjectResultList(examId, classId, subject, 0, 0);
    }

    public ExamResult getExamResult(long examId, long studentId, boolean withSubjectResult) {
        if (withSubjectResult) {
            ExamResultQuery query = new ExamResultQuery();
            query.setExamId(examId);
            query.setStudentId(studentId);
            List<ExamResultDO> results = examResultDao.selectByQuery(query);

            ExamResult result = new ExamResult();
            if (results.size() > 0) {
                for (ExamResultDO examResultDO : results) {
                    if (BizConstants.TOTAL_SCORE_SUBJECT.equals(examResultDO.getSubject())) {
                        ExamResult newResult = buildResult(examResultDO);
                        newResult.setSubjectResultMap(result.getSubjectResultMap());
                        result = newResult;
                        continue;
                    }
                    ExamSubjectResult subjectResult = buildSubjectResult(examResultDO);
                    result.addExamSubjectResult(subjectResult);
                }
            }
            return result;
        } else {
            ExamResultQuery query = new ExamResultQuery();
            query.setExamId(examId);
            query.setStudentId(studentId);
            query.setSubject(BizConstants.TOTAL_SCORE_SUBJECT);
            List<ExamResultDO> results = examResultDao.selectByQuery(query);

            ExamResult result = null;
            if (results.size() > 0) {
                result = buildResult(results.get(0));
            }
            return result;
        }
    }

    public ExamSubjectResult getSubjectResult(long examId, long studentId, String subject,
            boolean withQuestionResult) {
        ExamResultQuery query = new ExamResultQuery();
        query.setExamId(examId);
        query.setStudentId(studentId);
        query.setSubject(subject);
        List<ExamResultDO> results = examResultDao.selectByQuery(query);

        if (results.size() > 0) {
            ExamSubjectResult result = buildSubjectResult(results.get(0));

            if (withQuestionResult) {
                ExamResultDetailQuery questionQuery = new ExamResultDetailQuery();
                questionQuery.setResultId(result.getId());
                List<ExamResultDetailDO> questionResults = examResultDetailDao
                        .selectByQuery(questionQuery);
                if (questionResults.size() > 0) {
                    for (ExamResultDetailDO examResultDetailDO : questionResults) {
                        ExamQuestionResult questionResult = buildQuestionResult(examResultDetailDO);
                        questionResult.setSubjectResult(result);
                        result.addExamQuestionResult(questionResult);
                    }
                }
            }

            return result;
        } else {
            return null;
        }
    }

    public List<ExamQuestionResult> getQuestionResultList(ExamSubjectResult subjectResult) {
        return getQuestionResultList(subjectResult, 0, 0, false);
    }

    public List<ExamQuestionResult> getQuestionResultList(ExamSubjectResult subjectResult,
            int pageNumber, int pageSize, boolean orderByQuestionDesc) {
        List<ExamQuestionResult> list = new LinkedList<ExamQuestionResult>();
        if (subjectResult != null && subjectResult.getId() > 0) {
            ExamResultDetailQuery query = new ExamResultDetailQuery();
            query.setResultId(subjectResult.getId());
            query.setOrderByQuestionDesc(orderByQuestionDesc);
            if (pageNumber > 0 && pageSize > 0) {
                query.setPageNumber(pageNumber);
                query.setPageSize(pageSize);
            }
            List<ExamResultDetailDO> questionResults = examResultDetailDao.selectByQuery(query);

            if (questionResults.size() > 0) {
                for (ExamResultDetailDO examResultDetailDO : questionResults) {
                    ExamQuestionResult questionResult = buildQuestionResult(examResultDetailDO);
                    list.add(questionResult);
                }
            }
        }
        return list;
    }

    public ExamQuestionResult getQuestionResult(ExamSubjectResult subjectResult, int questionNumber) {
        if (subjectResult != null && subjectResult.getId() > 0) {
            ExamResultDetailQuery query = new ExamResultDetailQuery();
            query.setResultId(subjectResult.getId());
            query.setQuestionNumber(questionNumber);
            List<ExamResultDetailDO> questionResults = examResultDetailDao.selectByQuery(query);

            if (questionResults.size() > 0) {
                ExamQuestionResult questionResult = buildQuestionResult(questionResults.get(0));
                questionResult.setSubjectResult(subjectResult);
                return questionResult;
            }
        }
        return null;
    }

    private ExamQuestionResult buildQuestionResult(ExamResultDetailDO examResultDetailDO) {
        ExamQuestionResult result = new ExamQuestionResult();
        result.setQuestionNumber(examResultDetailDO.getQuestionNumber());
        result.setScore(examResultDetailDO.getScore());
        result.setAnswer(examResultDetailDO.getAnswer());
        if (examResultDetailDO.getTotalScore() != null) {
            result.setTotalScore(examResultDetailDO.getTotalScore());
        }
        if (examResultDetailDO.getCorrectAnswer() != null) {
            result.setCorrectAnswer(examResultDetailDO.getCorrectAnswer());
        }
        return result;
    }

    private ExamSubjectResult buildSubjectResult(ExamResultDO examResultDO) {
        ExamSubjectResult result = new ExamSubjectResult();
        result.setId(examResultDO.getId());
        result.setExamId(examResultDO.getExamId());
        result.setStudentId(examResultDO.getStudentId());
        result.setSubject(examResultDO.getSubject());
        result.setClassId(examResultDO.getClassId());
        result.setSchoolId(examResultDO.getSchoolId());
        result.setScore(examResultDO.getScore());
        result.setClassRank(examResultDO.getClassRank() != null ? examResultDO.getClassRank() : 0);
        result.setSchoolRank(examResultDO.getSchoolRank() != null ? examResultDO.getSchoolRank()
                : 0);

        result.setExamInfo(examService.getSimpleExam(examResultDO.getExamId()));
        return result;
    }

    private ExamResult buildResult(ExamResultDO examResultDO) {
        ExamResult result = new ExamResult();
        result.setExamId(examResultDO.getExamId());
        result.setStudentId(examResultDO.getStudentId());
        result.setClassId(examResultDO.getClassId());
        result.setSchoolId(examResultDO.getSchoolId());
        result.setScore(examResultDO.getScore());
        result.setClassRank(examResultDO.getClassRank() != null ? examResultDO.getClassRank() : 0);
        result.setSchoolRank(examResultDO.getSchoolRank() != null ? examResultDO.getSchoolRank()
                : 0);

        result.setExamInfo(examService.getSimpleExam(examResultDO.getExamId()));
        return result;
    }

    public Long insert(ExamResultDO examResult) {
        return examResultDao.insert(examResult);
    }
}
